﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataGenerator
{
    class Program
    {
        static int authorsCount = 0;
        static int publishersCount = 0;
        static int albumsCount = 0;
        static int newspapersCount = 0;

        static void Main(string[] args)
        {
            Console.WriteLine("Authors generating...");
            authorsCount = GenerateInserts(2, "../../lab4_data/authors.txt", "../../inserts/authors_inserts.sql", 12092039, GenerateAuthorsInternal);

            Console.WriteLine("Publishers generating...");
            publishersCount = GenerateInserts(2, "../../lab4_data/publishers.txt", "../../inserts/publishers_inserts.sql", 903748723, GeneratePublishersInternal);

            Console.WriteLine("Books generating...");
            GenerateInserts(7, "../../lab4_data/books.txt", "../../inserts/books_inserts.sql", 873437436, GenerateBooksInternal);

            Console.WriteLine("Albums generating...");
            albumsCount = GenerateInserts(12, "../../lab4_data/albums.txt", "../../inserts/albums_inserts.sql", 72632356, GenerateAlbumsInternal);

            Console.WriteLine("Songs generating...");
            GenerateInserts(21, "../../lab4_data/songs.txt", "../../inserts/songs_inserts.sql", 543236253, GenerateSongsInternal);

            Console.WriteLine("Newspapers generating...");
            newspapersCount = GenerateInserts(3, "../../lab4_data/newspapers.txt", "../../inserts/newspapers_inserts.sql", 543236253, GenerateNewspapersInternal);

            Console.WriteLine("Articles generating...");
            GenerateInserts(30, "../../lab4_data/articles.txt", "../../inserts/articles_inserts.sql", 3442334, GenerateArticlesInternal);

            Console.ReadLine();
        }

        static int GenerateInserts(
            int iterationNumber, 
            string dataPath, 
            string outputPath, 
            int seed, 
            Action<string, string[], StreamWriter, Random, int> generateInternal)
        {
            StreamWriter fileWriter = null;
            try 
            {
                string[] dataLines = File.ReadAllLines(dataPath, Encoding.UTF8);
                string[] countries = File.ReadAllLines("../../lab4_data/countries.txt", Encoding.UTF8);
                int countriesCount = countries.Count();
                fileWriter = new StreamWriter(outputPath, false);
                Random rand = new Random(seed);

                for (int i = 0; i < iterationNumber; i++)
                {
                    foreach (string dataLine in dataLines)
                    {
                        generateInternal(dataLine, countries, fileWriter, rand, i);
                    }
                }

                return dataLines.Count() * iterationNumber;
            }
            catch (IOException ex)
            {
                Console.WriteLine(ex);
                return 0;
            }
            finally
            {
                if (fileWriter != null)
                {
                    fileWriter.Close();
                }
            }
        }

        static void GenerateAuthorsInternal(string author, string[] countries, StreamWriter fileWriter, Random rand, int i)
        {
            int countriesCount = countries.Count();
            if (author != string.Empty)
            {
                string[] authorData = author.Split(new string[] { ",\t" }, StringSplitOptions.None);
                string authorName = authorData[0].Replace("'", string.Empty);
                string authorLastName = authorData[1].Replace("'", string.Empty);

                if (i != 0)
                {
                    authorName += i;
                    authorLastName += i;
                }

                string authorCountry = countries[rand.Next(0, countriesCount - 1)];
                DateTime authorBirthDate = GenerateRandomDate(rand);

                fileWriter.WriteLine(
                    string.Format("INSERT INTO AUTHORS (first_name, last_name, birth_date, country) VALUES ('{0}', '{1}', '{2}', '{3}');",
                    authorName,
                    authorLastName,
                    authorBirthDate.Date.ToShortDateString(),
                    authorCountry));
            }
        }

        static void GeneratePublishersInternal(string publisher, string[] countries, StreamWriter fileWriter, Random rand, int i)
        {
            int countriesCount = countries.Count();
            if (publisher != string.Empty)
            {
                string publisherName = publisher.Replace("'", string.Empty).Replace("&", string.Empty);

                if (i != 0)
                {
                    publisherName += i;
                }

                string publisherCountry = countries[rand.Next(0, countriesCount - 1)];
                DateTime publisherEstablishDate = GenerateRandomDate(rand);

                fileWriter.WriteLine(
                    string.Format("INSERT INTO PUBLISHERS (name, country, establish_date) VALUES ('{0}', '{1}', '{2}');",
                    publisherName,
                    publisherCountry,
                    publisherEstablishDate.Date.ToShortDateString()));
            }
        }

        static void GenerateBooksInternal(string book, string[] countries, StreamWriter fileWriter, Random rand, int i)
        {
            int countriesCount = countries.Count();
            if (book != string.Empty)
            {
                string[] bookData = book.Split(new string[] { ",\t" }, StringSplitOptions.None);
                string bookTitle = bookData[0].Replace("'", string.Empty).Replace("&", string.Empty);
                string bookPublicationYear = bookData[1].Replace("'", string.Empty);

                if (bookPublicationYear == string.Empty)
                {
                    bookPublicationYear = "1991";
                }

                if (i != 0)
                {
                    bookTitle += i;
                }

                string[] genres = new string[] { "romance", "science-fiction", "fantasy", "thriller", "biography" };
                DateTime publicationYear = new DateTime(Int32.Parse(bookPublicationYear), 1, 1);
                int authorId = rand.Next(1, authorsCount);
                int publisherId = rand.Next(1, publishersCount);
                int pageCount = rand.Next(50, 1500);
                string genre = genres[rand.Next(0, 4)];

                fileWriter.WriteLine(
                    string.Format("INSERT INTO BOOKS (title, publication_year, page_count, genre, author_id, publisher_id) VALUES ('{0}', '{1}', {2}, '{3}', {4}, {5});",
                    bookTitle,
                    publicationYear.Date.ToShortDateString(),
                    pageCount,
                    genre,
                    authorId,
                    publisherId));
            }
        }

        static void GenerateAlbumsInternal(string album, string[] countries, StreamWriter fileWriter, Random rand, int i)
        {
            int countriesCount = countries.Count();
            if (album != string.Empty)
            {
                string[] albumData = album.Split(new string[] { ",\t" }, StringSplitOptions.None);
                string albumTitle = albumData[0].Replace("'", string.Empty).Replace("&", string.Empty);
                string albumPublicationYear = albumData[1].Replace("'", string.Empty);
                string genre = albumData[2].Replace("'", string.Empty).Replace("&", string.Empty);

                if (albumPublicationYear == string.Empty)
                {
                    albumPublicationYear = "1991";
                }

                if (i != 0)
                {
                    albumTitle += i;
                }

                DateTime publicationYear = new DateTime(Int32.Parse(albumPublicationYear), 1, 1);
                int publisherId = rand.Next(1, publishersCount);
                int songsCount = rand.Next(5, 15);

                fileWriter.WriteLine(
                    string.Format("INSERT INTO ALBUMS (title, publication_year, songs_count, genre, publisher_id) VALUES ('{0}', '{1}', {2}, '{3}', {4});",
                    albumTitle,
                    publicationYear.Date.ToShortDateString(),
                    songsCount,
                    genre,
                    publisherId));
            }
        }

        static void GenerateSongsInternal(string song, string[] countries, StreamWriter fileWriter, Random rand, int i)
        {
            int countriesCount = countries.Count();
            if (song != string.Empty)
            {
                string songTitle = song.Replace("'", string.Empty).Replace("&", string.Empty); ;

                if (i != 0)
                {
                    songTitle += i;
                }

                int duration = rand.Next(2, 8);
                int authorId = rand.Next(1, authorsCount);
                int albumId = rand.Next(1, albumsCount);

                fileWriter.WriteLine(
                    string.Format("INSERT INTO SONGS (title, duration, author_id, album_id) VALUES ('{0}', INTERVAL '{1}' MINUTE, {2}, {3});",
                    songTitle,
                    duration,
                    authorId,
                    albumId));
            }
        }

        static void GenerateNewspapersInternal(string newspaper, string[] countries, StreamWriter fileWriter, Random rand, int i)
        {
            int countriesCount = countries.Count();
            if (newspaper != string.Empty)
            {
                string[] newspaperData = newspaper.Split(new string[] { ",\t" }, StringSplitOptions.None);
                string newspaperTitle = newspaperData[1].Replace("'", string.Empty).Replace(",", string.Empty).Replace("&", string.Empty);
                string country = newspaperData[0].Replace("'", string.Empty);

                if (i != 0)
                {
                    newspaperTitle += i;
                }

                string [] kinds = new string[] { "daily", "weekly", "monthly", "quarterly" };
                int publisherId = rand.Next(1, 120);
                string kind = kinds[rand.Next(0, 4)];

                fileWriter.WriteLine(
                    string.Format("INSERT INTO NEWSPAPERS (title, country, kind, publisher_id) VALUES ('{0}', '{1}', '{2}', {3});",
                    newspaperTitle,
                    country,
                    kind,
                    publisherId));
            }
        }

        static void GenerateArticlesInternal(string article, string[] countries, StreamWriter fileWriter, Random rand, int i)
        {
            int countriesCount = countries.Count();
            if (article != string.Empty)
            {
                string newspaperTitle = article.Replace("'", string.Empty).Replace(",", string.Empty).Replace("&", string.Empty);

                if (i != 0)
                {
                    newspaperTitle += i;
                }

                string[] kinds = new string[] { "politics", "sport", "economy", "essay", "reportage" };
                int authorId = rand.Next(1, authorsCount);
                string kind = kinds[rand.Next(0, 4)];
                int newspaperId =  rand.Next(1, newspapersCount);

                fileWriter.WriteLine(
                    string.Format("INSERT INTO ARTICLES (title, kind, author_id, newspaper_id) VALUES ('{0}', '{1}', {2}, {3});",
                    newspaperTitle,
                    kind,
                    authorId,
                    newspaperId));
            }
        }

        static DateTime GenerateRandomDate(Random rand)
        {
            int year = rand.Next(1900, 2012);
            int month = rand.Next(1, 12);
            int day = rand.Next(1, 28);

            return new DateTime(year, month, day);
        }
    }
}
